#include "util.h"

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "dwt_delay.h"

const uint32_t code0[] = {
	0x9c8dca37, 0xd558bab6, 0x3619953b, 0x7b465f71, 0xe14afe1d, 0xb7847633,
	0x9536c111, 0x040243ce, 0x35a66d7f, 0xb08793c8, 0x07fa369c, 0x8af36f84,
	0x1e8ba71a, 0x6834bda3, 0xbaaa7e68, 0xa4bd2564,
};
const uint32_t code[64] = {
	0xc85dd82f, 0xb3959a20, 0x37e060b0,
	0x30395104, //1--3
	0x0e758558, 0x9d3c10e4, 0x1271afd7, 0x4a9f55be,
	0x00570044, //0--8
	0x45d98b44, 0x3306728e, 0x6b233e0a, 0xfe86811d, 0x9fe80b3c, 0x456e5180,
	0x580807ed, 0x6f65531f, 0xbc6197cf, 0x030b7c1d, 0x7bc83246, 0xc408effb,
	0x50a976fa, 0xed546d96, 0x316d2f07, 0x850586ab, 0xef2e46d9,
	0x31323732, //2--26
	0x875cff55, 0xd7c7587b, 0x76c2b89a, 0x4cf738ee, 0x0d75f640, 0xd2a89896,
	0x93b8d134, 0x890cd999,
};

uint32_t code2[] = {
	0xe653935d, 0x88935f68, 0x644cd6b3, 0xcb739815, 0xac059f01, 0xc325cc7f,
	0x66326aef, 0x65532cb9, 0xd61c2021, 0x86b08419, 0xa2c15879, 0x92bf3265,
	0x3b462d68, 0xfa001a23, 0x9b37f3a1, 0x6a8037bc,
};

int getId0Pos(void)
{
	//return 8;
	return pow(2.0, 3.0);
}

int getId1Pos(void)
{
	//return 3;
	return 27 / 9;
}

int getId2Pos(void)
{
	//return 26;
	return 13 * (8 / 4);
}

/**
 * @brief sort string
 * 
 * @param strings 
 * @param num 
 */
void sortStrings(char *strings[], int num)
{
	char *temp;
	int top, seek;

	for (top = 0; top < num - 1; top++) {
		for (seek = top + 1; seek < num; seek++) {
			if (atoi(strings[top]) - atoi(strings[seek]) > 0) {
				temp = strings[top];
				strings[top] = strings[seek];
				strings[seek] = temp;
			}
		}
	}
}

/**
 * @brief Get the Uid object
 * 
 * @param uidbuf 
 */
void getUid(uint32_t *uidbuf)
{
	uidbuf[0] = (uint32_t)(READ_REG(*((uint32_t *)UID_BASE)));
	uidbuf[1] = (uint32_t)(READ_REG(*((uint32_t *)(UID_BASE + 4U))));
	uidbuf[2] = (uint32_t)(READ_REG(*((uint32_t *)(UID_BASE + 8U))));
}

/**
 * @brief 
 * 
 * @return int 
 */
int checkUid(void)
{
	uint8_t retval = 0;
	//printf("CODE GET: %08x %08x %08x \r\n", code[getId0Pos()], code[getId1Pos()], code[getId2Pos()] );
	//printf("UID  GET: %08x %08x %08x \r\n", HAL_GetUIDw0(), HAL_GetUIDw1(), HAL_GetUIDw2() );

	if (CHECK_ID) {
		if (code[getId0Pos()] != HAL_GetUIDw0()) {
			retval += 1;
		}

		if (code[getId1Pos()] != HAL_GetUIDw1()) {
			retval += 1;
		}

		if (code[getId2Pos()] != HAL_GetUIDw2()) {
			retval += 1;
		}
	}

	//printf("ID CHECK %d\r\n", retval);
	return retval;
}

int tolower(int c)
{
	if (c >= 'A' && c <= 'Z') {
		return c + 'a' - 'A';
	} else {
		return c;
	}
}

int htoi(char s[])
{
	int i;
	int n = 0;
	if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
		i = 2;
	} else {
		i = 0;
	}
	for (; (s[i] >= '0' && s[i] <= '9') || (s[i] >= 'a' && s[i] <= 'z') ||
	       (s[i] >= 'A' && s[i] <= 'Z');
	     ++i) {
		if (tolower(s[i]) > '9') {
			n = 16 * n + (10 + tolower(s[i]) - 'a');
		} else {
			n = 16 * n + (tolower(s[i]) - '0');
		}
	}
	return n;
}

/**
 * 比较版本号
 *
 * @param v1 第一个版本号
 * @param v2 第二个版本号
 *
 * @return 如果版本号相等，返回 0,
 *         如果第一个版本号低于第二个，返回 -1，否则返回 1.
 */
int compareVersion(const char *v1, const char *v2)
{
	assert_param(v1);
	assert_param(v2);

	const char *p_v1 = v1;
	const char *p_v2 = v2;

	while (*p_v1 && *p_v2) {
		char buf_v1[32] = { 0 };
		char buf_v2[32] = { 0 };

		char *i_v1 = strchr(p_v1, '.');
		char *i_v2 = strchr(p_v2, '.');

		if (!i_v1 || !i_v2)
			break;

		if (i_v1 != p_v1) {
			strncpy(buf_v1, p_v1, i_v1 - p_v1);
			p_v1 = i_v1;
		} else
			p_v1++;

		if (i_v2 != p_v2) {
			strncpy(buf_v2, p_v2, i_v2 - p_v2);
			p_v2 = i_v2;
		} else
			p_v2++;

		int order = atoi(buf_v1) - atoi(buf_v2);
		if (order != 0)
			return order < 0 ? -1 : 1;
	}

	double res = atof(p_v1) - atof(p_v2);

	if (res < 0)
		return -1;
	if (res > 0)
		return 1;
	return 0;
}

int int_pow(int n, int m)
{
	int i = 1;
	int sum = n;
	for (i = 1; i < m; i++) {
		sum = sum * n;
	}
	return sum;
}

void mdelay(u32 time)
{
	HAL_Delay(time);
}

void udelay(u32 time)
{
	DWT_Delay(time);
}
